import logging
import json
from datetime import datetime
from typing import Dict, Any, Optional
from enum import Enum

class PaymentLogLevel(Enum):
    """支付日志级别"""
    INFO = "INFO"
    WARNING = "WARNING"
    ERROR = "ERROR"
    CRITICAL = "CRITICAL"
    DEBUG = "DEBUG"

class PaymentEventType(Enum):
    """支付事件类型"""
    ORDER_CREATE = "ORDER_CREATE"
    ORDER_CALLBACK = "ORDER_CALLBACK"
    ORDER_QUERY = "ORDER_QUERY"
    ORDER_REFUND = "ORDER_REFUND"
    SIGNATURE_VERIFY = "SIGNATURE_VERIFY"
    NETWORK_REQUEST = "NETWORK_REQUEST"
    NETWORK_RESPONSE = "NETWORK_RESPONSE"
    SERVICE_ERROR = "SERVICE_ERROR"
    CONFIG_ERROR = "CONFIG_ERROR"

class PaymentLogger:
    """支付系统专用日志记录器"""
    
    def __init__(self, name: str = "payment"):
        self.logger = logging.getLogger(f"payment.{name}")
        self.logger.setLevel(logging.DEBUG)
        
        # 创建文件处理器
        if not self.logger.handlers:
            # 支付日志文件
            file_handler = logging.FileHandler('logs/payment.log', encoding='utf-8')
            file_handler.setLevel(logging.DEBUG)
            
            # 错误日志文件
            error_handler = logging.FileHandler('logs/payment_error.log', encoding='utf-8')
            error_handler.setLevel(logging.ERROR)
            
            # 格式化器
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
            )
            file_handler.setFormatter(formatter)
            error_handler.setFormatter(formatter)
            
            # 控制台处理器
            console_handler = logging.StreamHandler()
            console_handler.setLevel(logging.INFO)
            console_handler.setFormatter(formatter)
            
            self.logger.addHandler(file_handler)
            self.logger.addHandler(error_handler)
            self.logger.addHandler(console_handler)
    
    def log_payment_event(
        self,
        event_type: PaymentEventType,
        level: PaymentLogLevel,
        message: str,
        order_id: Optional[str] = None,
        user_id: Optional[int] = None,
        provider: Optional[str] = None,
        amount: Optional[float] = None,
        extra_data: Optional[Dict[str, Any]] = None
    ):
        """记录支付事件"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "event_type": event_type.value,
            "message": message,
            "order_id": order_id,
            "user_id": user_id,
            "provider": provider,
            "amount": amount,
        }
        
        if extra_data:
            log_data.update(extra_data)
        
        # 过滤敏感信息
        filtered_data = self._filter_sensitive_data(log_data)
        log_message = f"[{event_type.value}] {message} | Data: {json.dumps(filtered_data, ensure_ascii=False)}"
        
        if level == PaymentLogLevel.DEBUG:
            self.logger.debug(log_message)
        elif level == PaymentLogLevel.INFO:
            self.logger.info(log_message)
        elif level == PaymentLogLevel.WARNING:
            self.logger.warning(log_message)
        elif level == PaymentLogLevel.ERROR:
            self.logger.error(log_message)
        elif level == PaymentLogLevel.CRITICAL:
            self.logger.critical(log_message)
    
    def log_order_create(self, order_id: str, user_id: int, provider: str, amount: float, params: Dict[str, Any]):
        """记录订单创建"""
        self.log_payment_event(
            PaymentEventType.ORDER_CREATE,
            PaymentLogLevel.INFO,
            f"创建支付订单",
            order_id=order_id,
            user_id=user_id,
            provider=provider,
            amount=amount,
            extra_data={"params": params}
        )
    
    def log_callback_received(self, provider: str, raw_data: Dict[str, Any]):
        """记录支付回调接收"""
        self.log_payment_event(
            PaymentEventType.ORDER_CALLBACK,
            PaymentLogLevel.INFO,
            f"接收到支付回调",
            provider=provider,
            extra_data={"raw_callback_data": raw_data}
        )
    
    def log_signature_verify(self, provider: str, order_id: str, success: bool, error: str = None):
        """记录签名验证"""
        level = PaymentLogLevel.INFO if success else PaymentLogLevel.ERROR
        message = "签名验证成功" if success else f"签名验证失败: {error}"
        
        self.log_payment_event(
            PaymentEventType.SIGNATURE_VERIFY,
            level,
            message,
            order_id=order_id,
            provider=provider,
            extra_data={"signature_valid": success, "error": error}
        )
    
    def log_network_request(self, provider: str, url: str, method: str, headers: Dict, data: Any):
        """记录网络请求"""
        self.log_payment_event(
            PaymentEventType.NETWORK_REQUEST,
            PaymentLogLevel.DEBUG,
            f"发送网络请求到 {provider}",
            provider=provider,
            extra_data={
                "url": url,
                "method": method,
                "headers": self._filter_sensitive_data(headers),
                "data": self._filter_sensitive_data(data) if isinstance(data, dict) else str(data)[:200]
            }
        )
    
    def log_network_response(self, provider: str, url: str, status_code: int, response_data: Any):
        """记录网络响应"""
        level = PaymentLogLevel.INFO if 200 <= status_code < 300 else PaymentLogLevel.WARNING
        
        self.log_payment_event(
            PaymentEventType.NETWORK_RESPONSE,
            level,
            f"收到来自 {provider} 的响应",
            provider=provider,
            extra_data={
                "url": url,
                "status_code": status_code,
                "response": self._truncate_response(response_data)
            }
        )
    
    def log_service_error(self, provider: str, error: Exception, order_id: str = None, context: Dict = None):
        """记录服务错误"""
        self.log_payment_event(
            PaymentEventType.SERVICE_ERROR,
            PaymentLogLevel.ERROR,
            f"支付服务错误: {str(error)}",
            order_id=order_id,
            provider=provider,
            extra_data={
                "error_type": type(error).__name__,
                "error_message": str(error),
                "context": context
            }
        )
    
    def log_config_error(self, provider: str, missing_config: str):
        """记录配置错误"""
        self.log_payment_event(
            PaymentEventType.CONFIG_ERROR,
            PaymentLogLevel.CRITICAL,
            f"支付配置缺失: {missing_config}",
            provider=provider,
            extra_data={"missing_config": missing_config}
        )
    
    def _filter_sensitive_data(self, data: Any) -> Any:
        """过滤敏感数据"""
        if not isinstance(data, dict):
            return data
        
        sensitive_keys = [
            'password', 'secret', 'key', 'token', 'signature',
            'private_key', 'api_key', 'cert', 'certificate',
            'app_secret', 'mch_key', 'sign'
        ]
        
        filtered = {}
        for key, value in data.items():
            if any(sensitive in key.lower() for sensitive in sensitive_keys):
                filtered[key] = "***FILTERED***"
            elif isinstance(value, dict):
                filtered[key] = self._filter_sensitive_data(value)
            else:
                filtered[key] = value
        
        return filtered
    
    def _truncate_response(self, response_data: Any, max_length: int = 1000) -> Any:
        """截断长响应数据"""
        if isinstance(response_data, str):
            return response_data[:max_length] + "..." if len(response_data) > max_length else response_data
        elif isinstance(response_data, dict):
            return {k: str(v)[:100] + "..." if isinstance(v, str) and len(str(v)) > 100 else v 
                   for k, v in response_data.items()}
        else:
            return str(response_data)[:max_length]

# 创建全局支付日志记录器实例
payment_logger = PaymentLogger()